package com.bjtu.ptsite.tracker.service.impl;

import com.bjtu.ptsite.mapper.UserMapper;
import com.bjtu.ptsite.model.PageResult;
import com.bjtu.ptsite.model.Result;
import com.bjtu.ptsite.model.User;
import com.bjtu.ptsite.model.PageResult;
import com.bjtu.ptsite.tracker.client.TrackerClient;
import com.bjtu.ptsite.tracker.entity.TrackerMessage;
import com.bjtu.ptsite.tracker.entity.TrackerRequest;
import com.bjtu.ptsite.mapper.TrackerMessageMapper;
import com.bjtu.ptsite.tracker.service.TrackerService;
import com.bjtu.ptsite.utils.AliOSSUtils;
import com.bjtu.ptsite.utils.RequestUtil;
import com.bjtu.ptsite.utils.TorrentUtils;
import com.bjtu.ptsite.utils.UUIDUtils;
import com.turn.ttorrent.common.Torrent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.bjtu.ptsite.utils.TorrentUtils.parseTorrent;

@Slf4j
@Service
public class TrackerServiceImpl implements TrackerService {

    @Autowired
    private TrackerClient trackerClient;

    @Autowired
    private TrackerMessageMapper trackerMessageMapper;

    @Autowired
    private AliOSSUtils aliOSSUtils;

    @Autowired
    private UserMapper userMapper;

    @Value("${spring.tracker.url}")
    String trackerUrl;

    /**
     * 判断文件类型，将文件转换为torrent格式
     *
     * @param param
     * @param file
     * @return
     */
    @Override
    public String createTorrent(TrackerRequest param, MultipartFile file) {
        try {
            // return trackerClient.createTorrent();
            Integer identificationNumber = RequestUtil.getIdentificationNumber();
            if(identificationNumber==null){
                //设置默认用户管理员,仅用于测试
                identificationNumber=10000001;
            }
            User user = userMapper.selectByIdentificationNumber(identificationNumber);
            // todo 处理param
            String torrentPath = trackerClient.createTorrent(file, UUIDUtils.generateUUID(), user.getPassKey());
            File torrentFile = new File(torrentPath);
            Torrent torrent = parseTorrent(torrentFile);
            String originalFilename = file.getOriginalFilename();
            String hexInfoHash = "";
            long size = 0L;
            int fileCount = 0;
            if (torrent != null) {
                hexInfoHash = torrent.getHexInfoHash();
                size = torrent.getSize();
                fileCount = TorrentUtils.getFileCount(torrentFile);
            } else {
                log.error("解析torrent文件失败");
            }
            String messageId = UUIDUtils.generateUUID();
            // 生成日期路径
            String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            String fileName = datePath + "/" + messageId + ".torrent";
            String fileUrl = aliOSSUtils.uploadFile(torrentFile, fileName);
            // File downloadDir = new File("C:\\Torrent\\SourceSeed");
            // 手动做种
            // trackerClient.startSeedingIfNotStarted(torrentPath,downloadDir);
            TrackerMessage trackerMessage = TrackerMessage.builder()
                    .description(param.getDescription())
                    .category(param.getCategoryId())
                    .title(param.getTitle())
                    .messageId(messageId)
                    .fileSize(size)
                    .fileCount(fileCount)
                    .infoHash(hexInfoHash)
                    .isAnonymous(param.isAnonymous())
                    .uploaderId(identificationNumber)
                    .torrentPath(fileUrl)
                    .isFreeleech(param.isFreeleech())
                    .fileName(originalFilename)
                    .build();

            trackerMessageMapper.insert(trackerMessage);

            if (torrentFile.exists()) {
                boolean deleted = torrentFile.delete();
                if (!deleted) {
                    log.warn("临时 torrent 文件删除失败：{}", torrentFile.getAbsolutePath());
                }
            }
            return fileUrl;
        } catch (Exception e) {
           log.info("创建torrent文件失败，错误信息为：{}", e.getMessage(), e);
        }

        return null;
    }

    /**
     * 下载torrent文件
     *
     * @param param
     */
    @Override
    public Result getMagnet(TrackerRequest param) {

        TrackerMessage trackerMessage = trackerMessageMapper.selectById(param.getId());
        if (trackerMessage == null) {
            return Result.error("资源不存在");
        }

        String infoHash = trackerMessage.getInfoHash();
        String title = trackerMessage.getTitle();

        String magnetLink = String.format("magnet:?xt=urn:btih:%s&dn=%s&tr=%s",
                infoHash,
                URLEncoder.encode(title, StandardCharsets.UTF_8),
                URLEncoder.encode(trackerUrl, StandardCharsets.UTF_8));

        return Result.success(magnetLink);
    }

    @Transactional
    @Override
    public boolean uploadTorrent(TrackerRequest param) {
        MultipartFile torrentFile = param.getTorrentFile();
        Integer identificationNumber = RequestUtil.getIdentificationNumber();
        if(identificationNumber==null){
            identificationNumber=10000001;
        }
        User user = userMapper.selectByIdentificationNumber(identificationNumber);
        String messageId = UUIDUtils.generateUUID();
        String torrentPath = "";
        File file = null;
//        // 判断 torrentFile是torrent格式的还是其他格式的
//        if (torrentFile.getOriginalFilename().endsWith(".torrent")) {
//            try {
//                file = trackerClient.saveUploadedTorrent(torrentFile);
//            } catch (Exception e) {
//                log.error("保存torrent临时文件失败，错误信息为：{}", e.getMessage(), e);
//                return false;
//            }
//        } else {
            // 不是torrent格式的，需要先转换为torrent格式再上传
            //torrentPath = trackerClient.createTorrent(torrentFile, messageId, user.getPassKey());
            torrentPath = trackerClient.uploadTorrent(torrentFile, messageId, user.getPassKey());
            file = new File(torrentPath);
//        }

        String originalFilename = torrentFile.getOriginalFilename();
        String hexInfoHash = "";
        long size = 0L;
        int fileCount = 0;
        try {
            Torrent torrent = parseTorrent(file);
            if (torrent != null) {
                hexInfoHash = torrent.getHexInfoHash();
                size = torrent.getSize();
                fileCount = TorrentUtils.getFileCount(file);
            } else {
                log.error("解析torrent文件失败");
                return false;
            }

            // 生成日期路径
            String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            String fileName = datePath + "/" + messageId + ".torrent";
            String fileUrl = aliOSSUtils.uploadFile(file, fileName);
            // File downloadDir = new File("C:\\Torrent\\SourceSeed");
            // 手动做种
            // trackerClient.startSeedingIfNotStarted(torrentPath,downloadDir);
            TrackerMessage trackerMessage1 = trackerMessageMapper.selectByInfoHash(hexInfoHash);
            if(trackerMessage1!=null){
                if (file.exists()) {
                    boolean deleted = file.delete();
                    if (!deleted) {
                        log.warn("临时 torrent 文件删除失败：{}", file.getAbsolutePath());
                    }
                }
               throw new RuntimeException("该资源已存在");
            }else{
                TrackerMessage trackerMessage = TrackerMessage.builder()
                        .description(param.getDescription())
                        .category(param.getCategoryId())
                        .title(param.getTitle())
                        .messageId(messageId)
                        .fileSize(size)
                        .fileCount(fileCount)
                        .infoHash(hexInfoHash)
                        .isAnonymous(param.isAnonymous())
                        .uploaderId(identificationNumber)
                        .torrentPath(fileUrl)
                        .isFreeleech(param.isFreeleech())
                        .fileName(originalFilename)
                        .build();

                trackerMessageMapper.insert(trackerMessage);
                if (file.exists()) {
                    boolean deleted = file.delete();
                    if (!deleted) {
                        log.warn("临时 torrent 文件删除失败：{}", file.getAbsolutePath());
                    }
                }
                return true;
            }
        } catch (Exception e) {
           // log.error("加载torrent文件失败:{}", e.getMessage(), e);
            throw new RuntimeException(e.getMessage());
        }

    }

    @Override
    public void d() {
        try {
            trackerClient.don();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String downloadTorrent(TrackerRequest param, String passKey) {
        try {
            Integer id = param.getId();
            TrackerMessage trackerMessage = trackerMessageMapper.selectById(id);
            if (trackerMessage == null) {
                log.error("资源不存在");
                return null;
            }
            String filePath = trackerClient.downloadTorrent(trackerMessage, passKey);
            File file = new File(filePath);
            String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            String fileName = datePath + "/" + UUIDUtils.generateUUID() + ".torrent";
            String url = aliOSSUtils.uploadFile(file, fileName);
            if (file.exists()) {
                boolean deleted = file.delete();
                if (!deleted) {
                    log.warn("临时 torrent 文件删除失败：{}", file.getAbsolutePath());
                }
            }
            return url;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public PageResult<TrackerMessage> getTorrentList(int page, int size, Integer categoryId) {
        // 计算分页偏移量
        int offset = (page - 1) * size;

        // 分页查询
        List<TrackerMessage> torrents = trackerMessageMapper.selectTorrentsByPage(offset, size, categoryId);

        // 获取总记录数
        int total = trackerMessageMapper.selectTotalCount(categoryId);

        // 填充上传者信息
        List<TrackerMessage> enrichedList = enrichWithUploaderInfo(2, torrents);

        return new PageResult<>(total, enrichedList);
    }

    @Override
    public PageResult<TrackerMessage> getUserTorrentList(int flag, int userId, int page, int size, Integer categoryId) {
        // 计算分页偏移量
        int offset = (page - 1) * size;

        // 获取用户的识别号
        User user = userMapper.selectById(userId);
        int uploaderId = user.getIdentificationNumber();

        List<TrackerMessage> torrents = null;
        int total = 0;

        if (flag == 0) {
            // 分页查询
            torrents = trackerMessageMapper.selectTorrentsByUploaderWithPage(uploaderId, offset, size, categoryId);
            // 获取总记录数
            total = trackerMessageMapper.selectCountByUploader(uploaderId, categoryId);
        } else if (flag == 1) {
            // 分页查询
            torrents = trackerMessageMapper.selectTorrentsByUploaderWithPageWithoutAnonymous(uploaderId, offset, size, categoryId);
            // 获取总记录数
            total = trackerMessageMapper.selectCountByUploaderWithoutAnonymous(uploaderId, categoryId);
        }

        // 填充上传者信息
        List<TrackerMessage> enrichedList = enrichWithUploaderInfo(flag, torrents);

        return new PageResult<>(total, enrichedList);
    }

    @Override
    public boolean isConnect(TrackerRequest param) {
        //检测做种用户的公网以及端口是否可以连接
//        Integer identificationNumber = RequestUtil.getIdentificationNumber();
//        User user = userMapper.selectByIdentificationNumber(identificationNumber);
        Integer id = param.getId();
        TrackerMessage trackerMessage = trackerMessageMapper.selectById(id);
        String infoHash = trackerMessage.getInfoHash();
        return trackerClient.isConnect(infoHash);
    }

    @Override
    public boolean dumpRegisteredTorrents() {
        try {
            trackerClient.dumpRegisteredTorrents();
        } catch (Exception e) {
            log.error("dumpRegisteredTorrents error:{}", e.getMessage(), e);
            return false;
        }
        return true;
    }

    @Override
    public List<Map<String, Object>> listPeers(String infoHash) {
        return trackerClient.listPeers(infoHash);
    }

    @Override
    public TrackerMessage getSpTorrent(Integer id) {
        TrackerMessage torrent = trackerMessageMapper.selectById(id);
        if (torrent != null) {
            enrichSingleWithUploaderInfo(torrent);
        }
        return torrent;
    }

    // 填充单个种子的发布者信息，匿名
    private void enrichSingleWithUploaderInfo(TrackerMessage torrent) {
        if (torrent.getUploaderId() != null) {
            if (torrent.isAnonymous()) {
                torrent.setUserId(null);
                torrent.setUploaderId(null);
                torrent.setUserName("匿名用户");
                torrent.setAvatar(
                        "https://avatar-wzh.oss-cn-beijing.aliyuncs.com/51e0ff55-4166-4870-baad-fff1705cd3ea.png");
            } else {
                User uploader = userMapper.selectByIdentificationNumber(torrent.getUploaderId());
                if (uploader != null) {
                    torrent.setUserId(uploader.getUserId());
                    torrent.setUserName(uploader.getUsername());
                    torrent.setAvatar(uploader.getAvatar());
                }
            }
        }
    }

    //填充单个种子的发布者信息，无视匿名
    private void enrichSingleWithUploaderInfoWithoutAnonymous(TrackerMessage torrent) {
        if (torrent.getUploaderId() != null) {
            User uploader = userMapper.selectByIdentificationNumber(torrent.getUploaderId());
            if (uploader != null) {
                torrent.setUserId(uploader.getUserId());
                torrent.setUserName(uploader.getUsername());
                torrent.setAvatar(uploader.getAvatar());
            }
        }
    }

    // 批量填充发布者信息,flag为0表示无视匿名全部显示（如查看自己的种子），为1表示不填充匿名信息但要删除匿名的种子（如查看别人的种子），为2表示要填充匿名信息
    private List<TrackerMessage> enrichWithUploaderInfo(int flag, List<TrackerMessage> torrents) {
        if (flag == 0) {
            return torrents.stream().map(torrent -> {
                enrichSingleWithUploaderInfoWithoutAnonymous(torrent);
                return torrent;
            }).collect(Collectors.toList());
        } else if (flag == 1) {
            torrents.removeIf(TrackerMessage::isAnonymous);
            return torrents.stream().map(torrent -> {
                enrichSingleWithUploaderInfo(torrent);
                return torrent;
            }).collect(Collectors.toList());
        } else {
            return torrents.stream().map(torrent -> {
                enrichSingleWithUploaderInfo(torrent);
                return torrent;
            }).collect(Collectors.toList());
        }
    }
}
